# -*- coding: utf-8 -*-
import base64
import StringIO
# import csv
import datetime
import xlwt
import xlrd

from openerp.osv import osv, fields

# 提货记录导出
class apply_export_wizard(osv.osv):
    _name = 'apply.export.wizard'
    _columns = {
        'selected': fields.integer(u'当前已选', readonly=1),
        'exported': fields.integer(u'之前已导出', readonly=1),
        'filename': fields.char(u'文件名', readonly=1),
        'data': fields.binary(u'文件', readonly=1),
        'product_filename': fields.char(u'产品汇总文件名', readonly=1),
        'product_data': fields.binary(u'产品文件', readonly=1),
        'state': fields.selection([('1', '1'), ('2', '2')], string=u'状态'),
    }
    _defaults = {
        'selected': lambda s, c, u, ctx: len(ctx.get('active_ids')),
        'state': '1',
    }

    def model_export_data_header_field(self,cr,uid,selected,context=None):
        delivery_obj = self.pool.get('apply.delivery')
        field_names = ['copy_code', 'product_id', 'to_name', 'province_id', 'city_id', 'county_id', 'address',
                       'phone_number', 'mobile_number',
                       'estimated_ship_date', 'shipping_type', 'shipping_code']

        to_export_ids = delivery_obj.search(
            cr, uid, [('is_export', '=', False), ('id', 'in', selected)], order='delivery_product_list DESC', context=context)
        exported = len(context.get('active_ids')) - len(to_export_ids)
        header = [u"卡号", u"卡券种类", u"联系人", u"省", u"市", u"县", u"街道",
                  u"电话号码", u"手机号码", u"期望发货日期", u"快递方式", u"快递单号"]
        length = len(header)
        export_data = delivery_obj.export_data(
            cr, uid, selected, [field_names[name] for name in xrange(length)], context=context).get('datas', [])
        return header,export_data,exported

    def write_file_to_excel(self, export_data):
        xls = StringIO.StringIO()
        xls_workbook = xlwt.Workbook(encoding="utf8")
        data_sheet = xls_workbook.add_sheet('data')
        header = [u'客户' ,u'产品', u'数量']
        for i in range(len(header)):
            data_sheet.write(0, i, header[i])
        row = 1
        for record in export_data:
            for i in range(len(record)):
                if record[i]:
                    export_value = str(record[i])  # 将数字转成字符串，以免被excel变成科学计数法
                    data_sheet.write(row, i, export_value)
            row += 1
        xls_workbook.save(xls)
        xls.seek(0)
        out = base64.encodestring(xls.getvalue())
        return out

    def get_product_collect_file(self, cr, uid, to_export_ids, context=None):
        product_clolect_dict = {}
        for delivery in self.pool.get('apply.delivery').browse(cr, uid, to_export_ids, context=context):
            [product_clolect_dict.update({(line.name.replace(' ', ''), delivery.card_so_id.partner_id.name):
                                              line.product_uom_qty + product_clolect_dict.get((line.name.replace(' ', ''),
                                               delivery.card_so_id.partner_id.name), 0)})
             for line in delivery.so_id.order_line]
        partner_product_data = [(key[1], key[0], val)  for key, val in product_clolect_dict.iteritems()]
        return self.write_file_to_excel(sorted(partner_product_data,key=lambda product:product[0]))

    def return_vals_construction(self,cr,uid,ids,exported,this_id,out,to_export_ids,context=None):
        all_product_data = self.get_product_collect_file(cr, uid, to_export_ids, context=context)
        vals = {'data': out,
                'filename': u'提货记录%s.xls' % datetime.datetime.now().strftime("%Y-%m-%d"),
                'state': '2',
                'product_filename': u'产品汇总%s.xls' % datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                'product_data':  all_product_data,
                'exported': exported}
        self.write(cr, uid, ids, vals, context=context)
        return {
            'type': 'ir.actions.act_window',
            'res_model': 'apply.export.wizard',
            'view_mode': 'form',
            'view_type': 'form',
            'res_id': this_id,
            'views': [(False, 'form')],
            'target': 'new',
        }

    #确认导出
    def button_next(self, cr, uid, ids, context=None):

        if context is None:
            context = {}
        if isinstance(ids, int):
            this_id = ids
        else:
            this_id = ids[0]
        xls = StringIO.StringIO()
        # 发货记录导出的字段 [卡号 产品 快递单号 快递方式 联系人 省 市 县 街道 手机 电话 期望发货日期]
        xls_workbook = xlwt.Workbook(encoding="utf8")
        data_sheet = xls_workbook.add_sheet('data')
        selected = context.get('active_ids')
        header, export_data, exported,to_export_ids = self.model_export_data_header_field(cr,uid,selected,context=context)
        for i in range(len(header)):
            data_sheet.write(0, i, header[i])
        row = 1
        for record in export_data:
            for i in range(len(record)):
                if record[i]:
                    export_value = str(record[i])    # 将数字转成字符串，以免被excel变成科学计数法
                    data_sheet.write(row, i, export_value)
            row += 1

        xls_workbook.save(xls)
        xls.seek(0)
        out = base64.encodestring(xls.getvalue())
        return self.return_vals_construction(cr,uid,ids,exported,this_id,out,to_export_ids,context=context)

# 快递单号导入
class apply_import_wizard(osv.osv):
    _name = 'apply.import.wizard'
    _columns = {
        'selected': fields.integer(u'总导入条数', readonly=1),
        'imported': fields.integer(u'有效条数', readonly=1),
        'to_import': fields.text(u'需导入的有效条目'),
        'data': fields.binary(u'请选择文件上传'),
        'state': fields.selection([('1', '1'), ('2', '2')], string=u'状态'),
    }
    _defaults = {
        'state': '1',
    }
    def header_data(self,cr,uid,ids,context=None):

        return [u"卡号", u"卡券种类", u"联系人", u"省", u"市", u"县", u"街道",
                  u"电话号码", u"手机号码", u"期望发货日期",  u"快递方式", u"快递单号"]

    #确认导入
    def button_next(self, cr, uid, ids, context=None):
        delivery_obj = self.pool.get('apply.delivery')
        express_obj = self.pool.get('express.type')
        user_obj = self.pool.get('res.users')
        if context is None:
            context = {}
        if isinstance(ids, int):
            this_id = ids
        else:
            this_id = ids[0]
        this = self.browse(cr, uid, ids, context)[0]
        # 发货记录导出的字段 [卡号 产品 快递单号 快递方式 联系人 省 市 县 街道 手机 电话 期望发货日期]
        if this.data is None:
            raise osv.except_osv(u'错误', u'文件格式有误，请重新上传')
        xls_file = StringIO.StringIO(base64.decodestring(this.data))
        workbook = xlrd.open_workbook(file_contents=xls_file.read())
        worksheet = workbook.sheets()[0]
        header = self.header_data(cr,uid,ids,context=context)
        selected = 0  # 导入文件的总行数（不包含header行）
        to_import = []  # 有效的行数（已输入了快递单号和快递方式，且erp中未记录发货的）
        length = len(header)
        nrows = worksheet.nrows
        for i in range(nrows):
            selected += 1
            record = worksheet.row_values(i)
            # 验证首行是否与导出文件一致
            if i == 0:
                if record != [header[name] for name in xrange(length)]:
                    raise osv.except_osv(u'错误', u'文件格式有误，请重新上传')
            else:
                # 忽略未输入快递方式的
                if not record[header.index(u'快递方式')]:
                    continue
                # excel中输入的快递方式在系统里查不到，需要用户修正
                if not express_obj.search(cr, uid, [('name', '=', record[header.index(u'快递方式')])], context=context):
                    raise osv.except_osv(u'错误', u'输入的快递方式 %s 不存在' % record[
                                         header.index(u'快递方式')])
                # 如果用户修改了卡券号这一列，或者增加了行，报错
                if not delivery_obj.search(cr, uid, [('copy_code', '=', record[header.index(u'卡号')]), ('is_export', '=', True)], context=context):
                    raise osv.except_osv(u'错误', u'输入的卡券号 %s 未导出' % record[
                                         header.index(u'卡号')])
                # 券号、单号、快递方式都输入了才算有效记录
                if all([record[header.index(u'卡号')], record[header.index(u'快递方式')], record[header.index(u'快递单号')]]):
                    # 之前导入过的数据再次导入不报错，直接忽略(增加is_shipping的条件，防止有换货的卡券重复记录）
                    delivery_id = delivery_obj.search(
                        cr, uid, [('copy_code', '=', record[header.index(u'卡号')]), ('is_shipping', '=', False)], context=context)
                    if uid != 1:
                        apply_deliver_row = delivery_obj.browse(
                            cr, uid, delivery_id, context=context)
                        if apply_deliver_row.is_shipping:
                            raise osv.except_osv(u'错误',u'输入的卡券号 %s 已经发货' % record[0])

                    #users = user_obj.browse(cr, uid, uid, context=context)
                    to_import.append([record[header.index(u'卡号')], record[
                                 header.index(u'快递方式')], record[header.index(u'快递单号')]])

        if selected > 0:
            selected -= 1
        imported = len(to_import)
        vals = {'state': '2',
                'selected': selected,
                'imported': imported,
                'to_import': to_import}

        self.write(cr, uid, ids, vals, context=context)

        return {
            'type': 'ir.actions.act_window',
            'res_model': 'apply.import.wizard',
            'view_mode': 'form',
            'view_type': 'form',
            'res_id': this_id,
            'views': [(False, 'form')],
            'target': 'new',
        }

    def button_ok(self, cr, uid, ids, context=None):
        delivery_obj = self.pool.get('apply.delivery')
        express_obj = self.pool.get('express.type')
        move_obj = self.pool.get('account.move')
        to_import = eval(self.browse(cr, uid, ids, context=context).to_import)
        if not to_import:
            raise osv.except_osv(u'错误', u'文件中没有需要导入的行')
        send_sms_delivery_ids = []
        for code, express, number in to_import:
            delivery_ids = delivery_obj.search(
                cr, uid, [('copy_code', '=', code), ('is_shipping', '=', False),
                          ('change_apply_delivery_ids', '=', False), ('is_canceled', '=', False)], context=context)
            express_id = express_obj.search(
                cr, uid, [('name', '=', express)], context=context)[0]
            delivery_ship_obj = delivery_obj.browse(
                cr, uid, delivery_ids, context=context)
            if  len(delivery_ids) != 1:
                raise osv.except_osv(u'错误', u'一个卡券号码%s,存在多个非取消提货记录。' % code)
            # 以此判断来判断是否是门店修改快递方式。如果是修改就不再改变is_shipping。从而可以避免多次生成补助费用。
            context.update({'delay': True})
            if delivery_ship_obj.is_shipping:
                delivery_obj.write(cr, uid, delivery_ids,
                                   {'shipping_code': long(
                                       number), 'shipping_type': express_id},
                                   context=context)
            else:
                send_sms_delivery_ids.extend(delivery_ids)
                delivery_obj.write(cr, uid, delivery_ids,
                                           {'shipping_code': str(
                                               number), 'shipping_type': express_id, 'is_shipping': True},
                                           context=context)

        delivery_obj.delivery_send_sms(cr, uid, send_sms_delivery_ids, context=context)
        return True




# 外部发货记录导入
class apply_import_out_delivery_wizard(osv.osv):
    _name = 'apply.import.out.delivery.wizard'
    _columns = {
        'selected': fields.integer(u'总导入条数', readonly=1),
        'imported': fields.integer(u'有效条数', readonly=1),
        'to_import': fields.text(u'需导入的有效条目'),
        'data': fields.binary(u'请选择文件上传'),
        'template_data': fields.binary(u'模版', readonly=1),
        'template_file_name': fields.char(u'模版文件名', readonly=1),
        'state': fields.selection([('1', '1'), ('2', '2')], string=u'状态'),
    }
    _defaults = {
        'state': '1',
    }
    def header_data(self, cr, uid, context=None):

        return [u"订单ID", u"订单流水号", u"子流水号", u"站点名称", u"商品货号", u"商品", u"数量", u"供应价", u"订单总额",
                u"下单时间", u"备注", u"订单标记", u"状态", u"收货人姓名", u"收货人手机号", u"收货人地址", u"快递公司",
                u"快递单号", u"来源礼包"]

    #确认导入
    def button_next(self, cr, uid, ids, context=None):
        delivery_obj = self.pool.get('apply.delivery')
        product_obj = self.pool.get('product.product')
        express_obj = self.pool.get('express.type')
        partner_obj = self.pool.get('res.partner')
        user_obj = self.pool.get('res.users')
        if context is None:
            context = {}
        if isinstance(ids, int):
            this_id = ids
        else:
            this_id = ids[0]
        this = self.browse(cr, uid, ids, context)[0]
        if this.data is None:
            raise osv.except_osv(u'错误', u'文件格式有误，请重新上传')
        xls_file = StringIO.StringIO(base64.decodestring(this.data))
        workbook = xlrd.open_workbook(file_contents=xls_file.read())
        worksheet = workbook.sheets()[0]
        header = self.header_data(cr, uid, context=context)
        selected = 0  # 导入文件的总行数（不包含header行）
        to_import = []  # 有效的行数（已输入了快递单号和快递公司，且erp中未记录发货的）
        length = len(header)
        nrows = worksheet.nrows
        for i in range(nrows):
            selected += 1
            record = worksheet.row_values(i)
            # 验证首行是否与导出文件一致
            if i == 0:
                if record != [header[name] for name in xrange(length)]:
                    raise osv.except_osv(u'错误', u'文件格式有误，请重新上传')
                continue

            # 检查快递公司
            if not record[header.index(u'快递公司')]:
                raise osv.except_osv(u'错误', u'快递公司不能为空')
            # 检查快递单号
            if record[header.index(u'快递公司')] != u'自提' and not record[header.index(u'快递单号')]:
                raise osv.except_osv(u'错误', u'快递单号不能为空')
            # excel中输入的快递公司在系统里查不到，需要用户修正
            # 如果已经存在相同的外部订单ID，则跳过
            out_order_code = record[header.index(u'订单ID')]
            if isinstance(out_order_code, float):
                out_order_code = str(int(out_order_code))
            if delivery_obj.search(cr, uid, [('outer_order_ref', '=', out_order_code)], context=context):
                continue
            # 检查快递公司是否填写正确
            # express_type = header.index(u'快递公司')
            # if express_type and not express_obj.search(cr, uid, [('name', '=', record[express_type])], context=context):
            #     raise osv.except_osv(u'错误', u'输入的快递公司 %s 不存在' % record[express_type])

            # 券号、单号、快递公司都输入了才算有效记录
            if all([record[header.index(u'订单ID')], record[header.index(u'商品货号')], record[header.index(u'数量')]]):
                # 之前导入过的数据再次导入不报错，直接忽略
                # delivery_id = delivery_obj.search(
                #     cr, uid, [('copy_code', '=', record[header.index(u'卡号')])], context=context)
                # if uid != 1:
                #     apply_deliver_row = delivery_obj.browse(
                #         cr, uid, delivery_id, context=context)
                #     if apply_deliver_row.is_shipping:
                #         raise osv.except_osv(u'错误',u'输入的卡券号 %s 已经发货' % record[0])
                product_code = record[header.index(u'商品货号')]
                partner_name = record[header.index(u'站点名称')]
                express_corp = record[header.index(u'快递公司')]
                product_ids = product_obj.search(cr, uid, [('default_code', '=', product_code)], context=context)
                if not product_ids:
                    raise osv.except_osv(u'错误', u'系统里无此产品编号 %s， 请先添加产品' % product_code)
                cr.execute("SELECT id FROM res_partner WHERE name = %s", (partner_name,))
                partner_row = cr.fetchone()
                if not partner_row:
                    raise osv.except_osv(u'错误', u'系统里无此客户 %s， 请先添加客户' % partner_name)

                cr.execute("SELECT id FROM express_type WHERE name=%s", (express_corp,))
                shipping_type_row = cr.fetchone()
                if not shipping_type_row:
                    raise osv.except_osv(u'错误', u'系统里找不到快递类型%s, 请现在快递方式中添加此快递公司' % express_corp)

                row = {'product_id': product_ids[0], 'partner_id': partner_row[0], 'shipping_type': shipping_type_row[0]}
                for index, header_text in enumerate(header):
                    row.setdefault(header_text, record[index])
                to_import.append(row)


        if selected > 0:
            selected -= 1
        imported = len(to_import)
        vals = {'state': '2',
                'selected': selected,
                'imported': imported,
                'to_import': to_import}

        self.write(cr, uid, ids, vals, context=context)

        return {
            'type': 'ir.actions.act_window',
            'res_model': 'apply.import.out.delivery.wizard',
            'view_mode': 'form',
            'view_type': 'form',
            'res_id': this_id,
            'views': [(False, 'form')],
            'target': 'new',
        }

    def button_ok(self, cr, uid, ids, context=None):
        delivery_obj = self.pool.get('apply.delivery')
        sale_order_obj = self.pool.get('sale.order')
        to_import = eval(self.browse(cr, uid, ids, context=context).to_import)
        if not to_import:
            raise osv.except_osv(u'错误', u'文件中没有需要导入的行')

        apply_delivery_ids = []
        for row in to_import:
            outer_order_ref = row.get(u'订单ID')
            if isinstance(outer_order_ref, float):
                outer_order_ref = str(int(outer_order_ref))

            mobile_number = row.get(u'收货人手机号')
            if isinstance(mobile_number, float):
                mobile_number = str(int(mobile_number))

            shipping_code = row.get(u'快递单号')
            if isinstance(shipping_code, float):
                shipping_code = str(int(shipping_code))
            else:
                shipping_code = str(shipping_code).strip()
            if row.get(u'快递公司') == u'自提' and shipping_code == '':
                cr.execute("SELECT MAX(id) FROM apply_delivery")
                max_id_row = cr.fetchone()
                shipping_code = 'ZT' + str(max_id_row[0] + 1)

            values = {
                'outer_order_ref': outer_order_ref,
                'outer_shop_name': row.get(u'站点名称'),
                'copy_code': row.get(u'订单流水号'),
                'partner_id': row.get('partner_id'),
                'product_id': row.get('product_id'),
                #'product_name': row.get('product_id'),
                u'数量': row.get(u'数量'),
                'address': row.get(u'收货人地址'),
                'to_name': row.get(u'收货人姓名'),
                'ship_memo': row.get(u'备注'),
                'mobile_number': mobile_number,
                'shipping_type': row.get('shipping_type'),
                'shipping_code': shipping_code,
                'is_shipping': True,
                'is_export': True,
                'export_date': '1970-01-01',
                'estimated_ship_date': row.get(u'下单时间'),
            }
            apply_delivery_id = delivery_obj.create(cr, uid, values, context=context)
            if apply_delivery_id:
                cr.execute("UPDATE apply_delivery SET product_name=%s, delivery_product_list=%s WHERE id=%s",
                           (row.get('product_id'), row.get(u'商品'), apply_delivery_id))
                sale_order_ids = sale_order_obj.search(cr, uid, [('apply_delivery_id', '=', apply_delivery_id)], context=context)
                lock_result = sale_order_obj.locked_inventory_operation(cr, uid, sale_order_ids, context=context)
                if not lock_result:
                    raise osv.except_osv(u'错误', u'%s产品库存不足' % row.get(u'商品'))
            else:
                raise osv.except_osv(u'错误', u'%s外部订单导入失败' % row.get(u'订单ID'))
            apply_delivery_ids.append(apply_delivery_id)
            cr.execute("SELECT * FROM apply_delivery WHERE id=%s", (apply_delivery_id,))
            apply_rows = cr.fetchone()
            pass
        #批量出库
        delivery_obj.write(cr, uid, apply_delivery_ids, {'is_shipping': True}, context=context)
        return True

    #导出excel模版
    def export_template_xls(self, cr, uid, ids, context=None):
        xls = StringIO.StringIO()
        xls_workbook = xlwt.Workbook(encoding="utf8")
        data_sheet = xls_workbook.add_sheet('data')
        fileds_dict = self.header_data(cr, uid, context=context)
        for index, fields_string in enumerate(fileds_dict):
            data_sheet.write(0, index, fields_string)
        xls_workbook.save(xls)
        xls.seek(0)
        out = base64.encodestring(xls.getvalue())
        self.write(cr, uid, ids, {'template_data': out, 'template_file_name': u'模版.xls'}, context=context)
        return {
             'type' : 'ir.actions.act_url',
             'url': '/web/binary/saveas?model=' + self._name + '&field=template_data&id=%s&filename_field=template_file_name' % (ids[0]),
             'target': 'self',
        }